import { StringObject } from './declare'

/**
 * 当前环境为 Firefox 浏览器
 */
export const IS_FIREFOX = /Firefox\/\d+/.test(navigator.userAgent) && !/Seamonkey\/\d+/.test(navigator.userAgent) ? true : false

export enum EACH_RESULT {
  DELETE,
  BREAK,
  DELETE_AND_BREAK,
}

export function eachArray<T>(target: T[], callback: (value: T, index: number) => EACH_RESULT | void) {
  for (let index = 0; index < target.length; index++) {
    const result = callback(target[index], index)
    if (result === EACH_RESULT.DELETE) {
      target.splice(index--, 1)
    } else if (result === EACH_RESULT.DELETE_AND_BREAK) {
      target.splice(index--, 1)
      break
    } else if (result === EACH_RESULT.BREAK) {
      break
    }
  }
}

export function eachObject<T>(target: { [propName: string]: T }, callback: (value: T, key: string) => EACH_RESULT | void) {
  for (let key in target) {
    const result = Reflect.apply(callback, target, [target[key], key])
    if (result === EACH_RESULT.DELETE) {
      Reflect.deleteProperty(target, key)
    } else if (result === EACH_RESULT.DELETE_AND_BREAK) {
      Reflect.deleteProperty(target, key)
      break
    } else if (result === EACH_RESULT.BREAK) {
      break
    }
  }
}

/**
 * HTML 字符串转换为 DocumentFragment（用于存在多个同级跟节点的 HTML 字符串）
 * @param html HTML 字符串
 * @param allowTextNode 子节点中允许包含 TextNode 节点
 * @returns
 */
export function htmlToFragment(html: string, allowTextNode?: boolean) {
  const div = document.createElement('div')
  div.innerHTML = html
  const fragment = document.createDocumentFragment()
  Array.from(allowTextNode ? div.childNodes : div.children).forEach((node) => {
    fragment.append(node)
  })
  return fragment
}

/**
 * HTML 字符串转换为 DOM
 * @param html HTML 字符串
 * @returns DOM
 */
export function htmlToElement(html: string) {
  const div = document.createElement('div')
  div.innerHTML = html
  if (!div.firstElementChild) {
    throw new Error(`无效的HTML字符串：${html}`)
  }
  return div.firstElementChild as HTMLElement
}

export const UUID = /^[a-zA-Z][a-zA-Z0-9]*$/

/**
 * 生成唯一的 id attribute value
 * @param lenth 随机字符串的有效长度（有效长度 = 总长度 - 前缀长度）
 * @param prefix 随机字符串的前缀
 * @returns
 */
export function uuid(lenth: number = 4, prefix?: string) {
  lenth = lenth < 1 ? 1 : lenth > 12 ? 12 : lenth
  prefix = prefix && UUID.test(prefix) ? prefix : 'pe'
  return Math.random()
    .toString(16)
    .replace('0.', prefix)
    .slice(0, lenth + prefix.length)
}

export function lowerCase(str: string) {
  return str.trim().toLowerCase()
}

export function upperCase(str: string) {
  return str.trim().toUpperCase()
}

export function last<T extends any[] | NodeList>(array: T) {
  return array[array.length - 1]
}

export function offset(elem: HTMLElement) {
  let offset = 0
  let node: any = elem
  while ((node = node.previousSibling)) {
    offset++
  }
  return offset
}

/**
 * 是 <br> 或 <wbr>
 */
export function isBr(target: any) {
  return target instanceof HTMLBRElement
}

enum SplitTextType {
  /** 常规字符 */
  NORMAL,
  /** 实体字符 */
  ENTITY,
}
interface SplitText {
  char: string
  type: SplitTextType
}

export function textSplit(str: string) {
  const temp: SplitText[] = []
  while (str.length) {
    let char = str[0]
    let type = SplitTextType.NORMAL
    if (char === ' ') {
      char = '&nbsp;'
      type = SplitTextType.ENTITY
    } else if (char === '&') {
      const match = str.match(/^&[a-z];$/)
      if (match) {
        char = match[0]
        type = SplitTextType.ENTITY
      }
    }
    temp.push({ char, type })
    str = str.slice(char.length)
  }
  return temp
}

export function isElement(target: any): target is HTMLElement {
  return target instanceof HTMLElement
}

// export function cssToString(css: object) {
//   return Object.entries(css)
//     .map(([prop, value]) => `${prop}: ${value};`)
//     .join('')
// }
